/*
 *  Copyright 2001-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package ar.uba.fi.posgrado.economy.service;

import java.util.List;

import org.springframework.transaction.annotation.Propagation;

import ar.uba.fi.posgrado.academy.model.Course;
import ar.uba.fi.posgrado.common.exception.MissingArgumentException;
import ar.uba.fi.posgrado.common.exception.PosgradoException;
import ar.uba.fi.posgrado.common.exception.PosgradoRuntimeException;
import ar.uba.fi.posgrado.common.model.Student;
import ar.uba.fi.posgrado.common.model.User;
import ar.uba.fi.posgrado.common.service.GenericService;
import ar.uba.fi.posgrado.economy.exception.DebtRuleException;
import ar.uba.fi.posgrado.economy.model.Customer;
import ar.uba.fi.posgrado.economy.model.Debt;
import ar.uba.fi.posgrado.economy.model.DebtStatus;
import ar.uba.fi.posgrado.economy.model.DebtType;

/**
 * Servicio para {@link Debt Deudas}.<br>
 * Contiene todo lo referido a deudas.<br>
 * 
 * @author nicolas.gonzalez
 * @author pablo.tortorella
 * 
 * @see GenericService
 */
public interface DebtService extends GenericService<Debt> {

	/**
	 * Crea deudas para el alumno en el curso elegido y se las asigna al cliente
	 * recibido.<br>
	 * <br>
	 * 
	 * La informacion de las deudas esta en los Instalments del curso.<br>
	 * <br>
	 * 
	 * Cada Instalment indica el tipo de concepto a aplicar a cada una de las
	 * deudas.<br>
	 * <br>
	 * 
	 * A su vez, la fecha de vencimiento de las deudas esta tambien en el curso.<br>
	 * La fecha de la primer cuota es la fecha mencionada. Las demas son un mes
	 * despues de la ultima y asi sucesivamente.<br>
	 * <br>
	 * 
	 * En caso de error, arroja una exception.<br>
	 * <br>
	 * 
	 * La transaccionabilidad es {@link Propagation#REQUIRED required}, de
	 * manera q no necesita una transaccion creada.<br>
	 * 
	 * @param student
	 * @param course
	 *            Contiene toda la info de las deudas
	 * @param customer
	 * @throws PosgradoException
	 */
	public void createDebts(Student student, Course course, Customer customer)
			throws PosgradoException;

	/**
	 * Ejecuta los jobs de {@link #activateDebts()} y {@link #deActivateDebts()} en
	 * forma online.<br><br>
	 * 
	 * En caso de que el usuario no sea administrador, devuelve una exception.<br>
	 * 
	 * @param user Usuario del cual se espera q sea administrador.<br>
	 * @throws PosgradoException
	 */
	public void executeOnlineJobs(User user) throws PosgradoException;
	
	/**
	 * Activa las deudas que se tienen que activar.<br>
	 * La transaccionabilidad es {@link Propagation#MANDATORY mandatory}, lo q
	 * significa q en caso de no existir una transaccion arrastrada falle el
	 * servicio.<br>
	 * 
	 * @return Devuelve las deudas activadas
	 * @throws PosgradoException
	 *             En caso de algun problema
	 */
	public List<Debt> activateDebts() throws PosgradoException;

	/**
	 * Pasa Vencidas las deudas que se vencieron.<br>
	 * 
	 * Las deja en estado {@link DebtStatus#Vencida vencida}.<br>
	 * 
	 * La transaccionabilidad es {@link Propagation#MANDATORY mandatory}, lo q
	 * significa q en caso de no existir una transaccion arrastrada falle el
	 * servicio.<br>
	 * 
	 * @return Devuelve las deudas q se vencidas
	 * @throws PosgradoException
	 *             En caso de algun problema
	 */
	public List<Debt> deActivateDebts() throws PosgradoException;

	/**
	 * Devuelve una lista de Deudas por status y/o alumno.<br>
	 * Si ambos status y alumno son nulos entonces devuelve todas las deudas.<br>
	 * 
	 * @param status
	 *            Si es nulo entonces no lo tiene en cuenta
	 * @param student
	 *            Si es nulo entonces no lo tiene en cuenta
	 * @return
	 * @throws PosgradoRuntimeException
	 * @throws PosgradoException
	 */
	public List<Debt> getDebtsByConditions(DebtStatus status, Student student)
			throws PosgradoRuntimeException, PosgradoException;

	/**
	 * Devuelve una lista de Deudas por cualquiera de los atributos de la deuda
	 * recibida por parametro.<br>
	 * <br>
	 * 
	 * <b>Importante: </b> Los resultados estan ordenados por el apellido del
	 * alumno y fecha de vencimiento.<br>
	 * <br>
	 * 
	 * La fecha de vencimiento es Menor o Igual.<br>
	 * La fecha desde es Mayor o Igual<br>
	 * 
	 * @param debt
	 *            Deuda con los parametros de busqueda cargados
	 * @return
	 * @throws PosgradoRuntimeException
	 * @throws PosgradoException
	 */
	public List<Debt> getDebtsByConditions(Debt debt)
			throws PosgradoRuntimeException, PosgradoException;

	/**
	 * Es igual a {@link #getDebtsByConditions(Debt)} pero solo trae aquellas
	 * deudas con estado = desiredStatus
	 * 
	 * @param desiredStatus
	 * @see #getDebtsByConditions(Debt)
	 */
	public List<Debt> getDebtsByConditions(Debt debt,
			List<DebtStatus> desiredStatus) throws PosgradoRuntimeException,
			PosgradoException;

	/**
	 * Busca los {@link DebtType}s
	 * 
	 * @return
	 * @throws PosgradoRuntimeException
	 * @throws PosgradoException
	 */
	public List<DebtType> getAllDebtTypes() throws PosgradoRuntimeException,
			PosgradoException;

	/**
	 * Busca el {@link DebtType} por id
	 * 
	 * @param debtTypeId
	 * @return
	 * @throws PosgradoRuntimeException
	 * @throws PosgradoException
	 */
	public DebtType getDebtTypeById(Long debtTypeId)
			throws PosgradoRuntimeException, PosgradoException;

	/**
	 * Devuelve el saldo menos beneficios y descuentos.<br>
	 * <b>Solo</b> aplica los descuentos y beneficios en el caso en q
	 * {@link Debt#getBalance()} = {@link Debt#getOriginalBalance()}.<br>
	 * Caso contrario devuelve el {@link Debt#getBalance()} ya que los
	 * beneficios y descuentos ya se aplicaron.<br>
	 * 
	 * Primero se aplican los descuentos y beneficios de porcentaje y luego los
	 * valores.<br>
	 * Esto <b>es</b> importante xq el importe final cambia.<br>
	 * 
	 * @param debt
	 * @return
	 * @throws PosgradoRuntimeException
	 * @throws PosgradoException
	 */
	public Double getBalanceWithBenefitsAndDicounts(Debt debt)
			throws PosgradoRuntimeException, PosgradoException;

	/**
	 * Devuelve en un String la informacion de descuentos y porcentajes.<br>
	 * <br>
	 * Sigue la forma:<br>
	 * <i>Benef: 15%|$150 Desc: 17%|$0</i><br>
	 * <i>Benef: 0%|$70 Desc: 0%|$0</i><br>
	 * <i>No aplica</i><br>
	 * 
	 * @param debt
	 * @return
	 */
	public String assembleDiscountsAndBenefitsDescription(Debt debt);

	/**
	 * @see ar.uba.fi.posgrado.common.service.GenericService#create(java.lang.Object)
	 */
	public void create(Debt debt) throws MissingArgumentException,
			DebtRuleException, PosgradoException;

	/**
	 * Devuelve una lista de Deudas por status y/o alumno.<br>
	 * Si ambos status y alumno son nulos entonces devuelve todas las deudas.<br>
	 * 
	 * @param status
	 *            Si es nulo entonces no lo tiene en cuenta
	 * @param customer
	 *            Si es nulo entonces no lo tiene en cuenta
	 * @return
	 */
	public List<Debt> getDebtsByConditions(DebtStatus status, Customer customer)
			throws PosgradoRuntimeException, PosgradoException;

}
